package com.sinsz.wxpn.open.support;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.sinsz.wxpn.exception.WxpnException;
import org.apache.commons.lang3.StringUtils;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 格式化接口相关参数与返回值工具
 * @author chenjianbo
 * @date 2018-11-15
 */
public final class FormaterUtils {

    private FormaterUtils() {
    }

    /**
     * 下划线转驼峰
     * @param arg0
     * @return
     */
    private synchronized static String underline2Hump(String arg0) {
        if (arg0 == null || "".equals(arg0.trim())) {
            return "";
        }
        int len = arg0.length();
        StringBuilder builder = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = arg0.charAt(i);
            if (c == '_') {
                if (++i < len) {
                    builder.append(Character.toUpperCase(arg0.charAt(i)));
                }
            } else {
                builder.append(c);
            }
        }
        return builder.toString();
    }

    /**
     * 格式化map，将key转换为驼峰模式
     * <p>
     *     待优化
     * </p>
     * @param map   待转换对象
     * @return      新的map
     */
    @SuppressWarnings(value = {"unchecked"})
    private static Map<String, Object> format(Map<String, Object> map) {
        return map.entrySet()
                .stream()
                .filter(entry -> entry.getValue() != null)
                .map(entry -> {
                    if (entry.getValue() instanceof Map) {
                        return new DefaultEntry(FormaterUtils.underline2Hump(entry.getKey()), format((Map<String, Object>) entry.getValue()));
                    } else if (entry.getValue() instanceof List) {
                        List<Object> list = (List<Object>) ((List) entry.getValue())
                                .stream()
                                .filter(Objects::nonNull)
                                .map(mapper -> {
                                    if (mapper instanceof Map) {
                                        return format((Map<String, Object>) mapper);
                                    } else {
                                        return mapper;
                                    }
                                })
                                .collect(Collectors.toList());
                        return new DefaultEntry(FormaterUtils.underline2Hump(entry.getKey()), list);
                    } else {
                        return new DefaultEntry(FormaterUtils.underline2Hump(entry.getKey()), entry.getValue());
                    }
                })
                .collect(Collectors.toMap(DefaultEntry::getKey, DefaultEntry::getValue));
    }

    /**
     * 默认的返回值格式化
     * @param content   请求返回值内容
     * @return
     */
    public static String defaultFormat(String content) {
        if (StringUtils.isEmpty(content)) {
            throw new WxpnException("请求失败.");
        }
        Map<String, Object> map = Json.fromJsonAsMap(Object.class, content);
        if (map.isEmpty()) {
            throw new WxpnException("请求无结果.");
        }
        Map<String, Object> result = FormaterUtils.format(map);
        return Json.toJson(result, JsonFormat.tidy());
    }

    /**
     * 获取post参数
     * @param request   参数请求对象
     * @return
     */
    public static String requestBodyParams(HttpServletRequest request) {
        try(ByteArrayOutputStream baos = new ByteArrayOutputStream();
            InputStream is = request.getInputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            return new String(baos.toByteArray(),"UTF-8");
        } catch (IOException e) {
            e.printStackTrace(System.out);
            throw new WxpnException("获取Post请求参数异常.");
        }
    }

    /**
     * 验证签名SHA1
     * @param str   待加密串
     * @return
     */
    public synchronized static String signatureSha1(String str) {
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));
            byte[] md = mdTemp.digest();
            int j = md.length;
            char[] buf = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 格式化接收到的消息
     * @param xmlMessage    xml格式的消息内容
     * @return              json字符串消息
     */
    @SuppressWarnings(value = {"unchecked"})
    public synchronized static String formatReceiveMessage(String xmlMessage) {
        try {
            XmlMapper mapper = new XmlMapper();
            Map map = mapper.readValue(xmlMessage, Map.class);
            ReceiveEntry entry = new ReceiveEntry(
                    map.getOrDefault("FromUserName", "").toString(),
                    map.getOrDefault("ToUserName", "").toString(),
                    map.getOrDefault("MsgType", "").toString(),
                    map.getOrDefault("Event", "").toString()
            );
            entry.setBody(map);
            return FormaterUtils.defaultFormat(Json.toJson(entry, JsonFormat.tidy()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "{}";
    }

}
